<template>
  <div
    :id="ConfigurationId"
    class="vc-leading-none vc-h-full vc-w-full vc-relative vc-overflow-hidden"
    :class="[isEditor ? 'vc-flex vc-flex-col' : '']"
  >
    <template v-if="isEditor">
      <TopMenu />
      <div class="vc-flex-1 vc-overflow-hidden">
        <div class="vc-h-full vc-flex vc-flex-row">
          <!-- 图例 -->
          <Legend :show-svg-detail="showSvgDetail" />
          <!-- svg and panel -->
          <Main
            :show-contextmenu="showContextmenu"
            :is-editor="true"
            :comp-data="compData"
            @load="onMainLoadCompData"
          />
        </div>
      </div>
      <div
        v-if="contextmenuData"
        class="
          vc-absolute vc-border vc-border-gray-400 vc-shadow-md vc-z-1050 vc-bg-white vc-rounded-md vc-overflow-visible
        "
        :style="{ left: contextmenuLeft, top: contextmenuTop }"
      >
        <div
          v-for="el in contextmenuData"
          :key="el.name"
          class="vc-relative"
          :class="{ 'vc-z-10': el.children }"
          @click="clickContextmenuItem(el)"
          @mouseenter="el.showSubMenu = true"
          @mouseleave="el.showSubMenu = false"
        >
          <div v-if="el.split" class="vc-h-px vc-my-2 vc-bg-gray-300"></div>
          <div
            v-else
            class="
              hover:vc-bg-blue-500 hover:vc-text-white
              vc-cursor-pointer vc-flex vc-flex-row vc-items-center vc-px-3 vc-py-2
            "
          >
            <div class="vc-flex-1">
              {{ el.name }}
            </div>
            <Icon v-if="el.children" name="arrow-right" />
          </div>
          <div
            v-if="el.children && el.showSubMenu"
            class="
              vc-absolute
              vc-top-0
              vc-left-full
              vc--ml-2
              vc-border
              vc-border-gray-400
              vc-shadow-md
              vc-z-1050
              vc-bg-white
              vc-rounded-md
            "
          >
            <div
              v-for="item in el.children"
              :key="item.name"
              class="vc-px-3 vc-py-2 hover:vc-bg-blue-500 hover:vc-text-white vc-cursor-pointer vc-whitespace-nowrap"
              @click="clickContextmenuItem(item)"
            >
              {{ item.name }}
            </div>
          </div>
        </div>
      </div>
      <div v-show="svgDetailVisible" class="vc-absolute vc-inset-0 vc-z-40">
        <div class="vc-absolute vc-inset-0 vc-bg-black vc-bg-opacity-20" @click="svgDetailVisible = false"></div>
        <div
          class="vc-absolute vc--translate-x-1/2 vc--translate-y-1/2 vc-left-1/2 vc-top-1/2 vc-bg-white vc-rounded-md"
        >
          <h2 class="vc-font-semibold vc-text-xl vc-mt-2 vc-text-center">{{ curDeviceSvgName }}</h2>
          <div class="vc-p-2 vc-border-b vc-border-gray-300">
            w:{{ svgDetailData.w }} h:{{ svgDetailData.h }} x:{{ svgDetailData.x }} y:{{ svgDetailData.y }} x%:{{
              (svgDetailData.x / svgDetailData.w).toFixed(2)
            }}
            y%:{{ (svgDetailData.y / svgDetailData.h).toFixed(2) }}
          </div>
          <div id="svgDetail" class="vc-relative" :style="{ width: svgDetailSize + 'px' }" @click="clickSvgDetail">
            <component :is="curDeviceSvg" v-if="curDeviceSvg" :width="svgDetailSize" />
          </div>
        </div>
      </div>
    </template>
    <Main
      v-else
      :show-contextmenu="showContextmenu"
      :is-editor="isEditor"
      :comp-data="compData"
      @load="onMainLoadCompData"
    />
    <Zoom
      v-if="!isEditor"
      v-model="previewScale"
      class="vc-absolute vc-top-2 vc-right-2"
      @change="previewScaleChange"
    />
    <!-- <Logger /> -->
  </div>
</template>
<script lang="ts" setup>
import "/@/style/tailwind.css";
import "/@/style/animate.css";
import "https://at.alicdn.com/t/font_3035765_zp71fb8psi.js";
import { ref, provide, shallowRef, reactive, watch } from "vue";
import { ConfigurationInstanceObj } from "/@/components/types";

import { useConnection } from "./useConnection";
import Icon from "/@/components/base/Icon.vue";
import { SvgHeight, SvgWidth } from "/@/components/common";
import TopMenu from "./TopMenu.vue";
import Legend from "./Legend.vue";
import Main from "./Main.vue";
import {
  ConfigurationEl,
  ContextmenuItem,
  DeviceImageLegend,
  DeviceSvgLegend,
  FlowPathLegend,
  PipePathLegend,
  RootCommonKey,
  ConfigurationMode,
  ConfigurationExpose,
} from "./types";
import { buildShortUUID } from "/@/utils/uuid";
import { Condition } from "./ConditionPanel/types";
import Logger from "/@/components/base/Logger.vue";
import Zoom from "/@/components/base/Zoom.vue";

const props = withDefaults(
  defineProps<{
    mode?: ConfigurationMode;
    //组件数据
    compData?: any;
    //数据点绑定的数据
    data?: any;
  }>(),
  {
    mode: ConfigurationMode.Apply,
  }
);
const emits = defineEmits(["loadCompData", "select"]);

const isEditor = ref(props.mode === ConfigurationMode.Editor);
const ConfigurationId = buildShortUUID("Configuration");
/**
 * 数据点绑定数据处理
 */
function handleData(data) {
  if (data && !isEditor.value) {
    for (const id in compInstance) {
      const ins = compInstance[id];
      if (ins.handleData) {
        ins.handleData(data);
      }
    }
  }
}
function onMainLoadCompData() {
  handleData(props.data);
  emits("loadCompData");
}
watch(
  () => props.data,
  (data) => {
    handleData(data);
  }
);
/**
 * contextmenu
 */
const contextmenuData = ref<ContextmenuItem[] | null>(null);
const contextmenuLeft = ref<string | undefined>();
const contextmenuTop = ref<string | undefined>();
function clickContextmenuItem(el: ContextmenuItem) {
  if (el.handler) {
    el.handler();
    contextmenuData.value = null;
  }
}
function showContextmenu(e: MouseEvent | null, data?: ContextmenuItem[]) {
  if (e === null) {
    contextmenuData.value = null;
    return;
  }
  contextmenuLeft.value = e.pageX + "px";
  contextmenuTop.value = e.pageY + "px";
  contextmenuData.value = data || [];
}

/**
 * svg detail
 */
const svgDetailSize = ref(400);
const svgDetailVisible = ref(false);
const curDeviceSvgName = ref("");
const svgDetailData = reactive({
  w: 1,
  h: 1,
  x: 0,
  y: 0,
});
function showSvgDetail(el) {
  curDeviceSvg.value = el.comp;
  curDeviceSvgName.value = el.name;
  svgDetailVisible.value = true;
}
const curDeviceSvg = shallowRef(null);
function clickSvgDetail(e: MouseEvent) {
  const el = document.getElementById("svgDetail");
  Object.assign(svgDetailData, {
    w: el?.offsetWidth,
    h: el?.offsetHeight,
    x: e.offsetX,
    y: e.offsetY,
  });
}
/**
 * 初始化子组件间的连接关系对象
 */
const connection = useConnection();
/**
 * provide common to root components
 */
const scaleFactor = ref(1);
const svgWidth = ref(SvgWidth);
const svgHeight = ref(SvgHeight);
watch(scaleFactor, (v) => {
  svgWidth.value = SvgWidth * v;
  svgHeight.value = SvgHeight * v;
});
const pipePathData = ref<ConfigurationEl[]>([]);
const deviceImageData = ref<ConfigurationEl[]>([]);
const deviceSvgData = ref<ConfigurationEl[]>([]);
const labelValueData = ref<ConfigurationEl[]>([]);
const flowPathData = ref<ConfigurationEl[]>([]);
const compInstance: ConfigurationInstanceObj = {};
const pipePathLegendData = shallowRef<PipePathLegend[]>([]);
const deviceImageLegendData = shallowRef<DeviceImageLegend[]>([]);
const deviceSvgLegendData = shallowRef<DeviceSvgLegend[]>([]);
const flowPathLegendData = ref<FlowPathLegend[]>([]);
//预览模式下的缩放系数
const previewScale = ref(1);
const previewScaleChange = shallowRef(() => {});
provide(RootCommonKey, {
  cid: ConfigurationId,
  deviceSvgData,
  deviceImageData,
  pipePathData,
  labelValueData,
  flowPathData,
  compInstance,
  connection,
  scaleFactor,
  svgWidth,
  svgHeight,
  pipePathLegendData,
  deviceImageLegendData,
  deviceSvgLegendData,
  flowPathLegendData,
  previewScale,
  previewScaleChange,
  selectItem(e) {
    emits("select", e);
  },
});
/**
 * expose
 */
const myExpose: ConfigurationExpose = {
  getCompConditionInfo() {
    const info: { [name: string]: Condition[] } = {};
    for (const id in compInstance) {
      const ins = compInstance[id];
      if (ins.getConditionData && ins.getDisplayInfo) {
        const data = ins.getConditionData();
        if (data.length > 0) {
          info[ins.getDisplayInfo().name] = data;
        }
      }
    }
    return info;
  },
  getLabelValueKeys() {
    const keys: string[] = [];
    for (const id in compInstance) {
      const ins = compInstance[id];
      if (ins.getDataKey) {
        const key = ins.getDataKey();
        key && keys.push(key);
      }
    }
    return keys;
  },
};
defineExpose(myExpose);
</script>
